function [mdat, sdat, mnmat, snmat, mbpr, sbpr] = synth_nmat_mix(mnmat, varargin)
% function [mdat, sdat, mnmat, snmat, mbpr, sbpr] = synth_nmat_mix(mnmat, varargin)
% 
% Synthesize an nmat, both by channel and as a mixture, and return the
% resulting synthesized data, nmats, and binary pianorolls.
%
% Input:
%   mnmat    [mat]  - Note matrix to render
%  OPTIONAL (passed in name-value pairs):
%   dsr      [num]  - Desired sampling rate [8000]
%   mono     [bool] - Render mono? [1]
%   nfft     [num]  - FFT size [512]
%   win      [num]  - FFT window size in seconds [0.064]
%   hop      [num]  - FFT window hop size in seconds [0.016]
%   tempo    [num]  - Tempo (in BPM) to render MIDI file at.  Empty means  
%                     leave the note matrix alone [[]]
%   pitches  [vec]  - MIDI note number range to use in symbolic output [20:100]
%   vel      [num]  - Velocity to use for notes in mnmat.  If [], leave alone [[]]
%   cfg      [str]  - Timidity config file to use ['']
%   trim_end [num]  - If greater than 0, the rendered output will be
%                     'trimmed' so that excess silence is removed. The
%                     actual value of trim_end is used as a threshold.  If 0, 
%                     we trim based on the implied length of mnmat, if 
%                     negative, we don't trim at all. [-1]
%   insts    [vec]  - General MIDI numbers to use for each channel.
%                     If empty, leave things alone. [[]]
%   ttype    [str]  - Transform type to use (see st_type.m) 'spec'
%   bpo      [num]  - Bands per octave (only for Constrant-Q) [12]
%   min_freq [num]  - Minimum frequency to keep for Constant-Q [40]
%   pad_std  [num]  - If sources have different lengths, we need to pad the
%                     shorter ones to make them the same length.  This 
%                     parameter determines how this is done.  If a non-negative 
%                     value is given, it is taken as the variance of
%                     Gaussian white noise that is used as filler.  If
%                     pad_std is negative, we use the variance of the last
%                     abs(pad_std) samples of the source that we're padding,
%                     and if pad_std is empty, no padding is done. [0] 
%
% Output:
%   dat      [mat]  - Audio samples (nsamples x nchannels)
%   sr       [num]  - Sampling rate of audio samples.  Just returned for
%                     convenience.

% Copyright (C) 2010-2030 Graham Grindlay (grindlay@ee.columbia.edu)
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% process arguments
[dsr, mono, nfft, win, hop, tempo, pitches, vel, cfg, trim_end, insts, ...
 ttype, bpo, minf, pad_std] = ...
    parse_opt(varargin, 'dsr', 8000, 'mono', 1, 'nfft', 512, 'win', 0.064, ...
                        'hop', 0.016, 'tempo', [], 'pitches', [20 100], ...
                        'vel', [], 'cfg', '', 'trim_end', -1, 'insts', [], ...
                        'ttype', 'spec', 'bpo', 12, 'min_freq', 40, ...
                        'pad_std', 0);

[d,sr] = synth_nmat(mnmat, 'mono', mono, 'tempo', tempo, 'vel', vel, ...
                    'cfg', cfg, 'dsr', dsr, 'insts', insts, ...
                    'trim_end', trim_end);

% compute the STFT
mdat = st_trans(d, ttype, 'dsr', dsr, 'nfft', nfft, 'win', win, ...
                   'hop', hop, 'bpo', bpo, 'min_freq', minf, 'mag_only', 1);
        
mbpr = binary_pianoroll(mnmat, size(mdat,2), 'pitches', pitches);

chans = unique(channel(mnmat));
S = length(chans);

sdat = cell(1,S);
snmat = cell(1,S);
sbpr = cell(1,S);
d = cell(1,S);
for s = 1:S
    snmat{s} = mnmat(channel(mnmat)==chans(s),:);
    [d{s},sr] = synth_nmat(snmat{s}, 'mono', mono, 'tempo', tempo, ...
                           'vel', vel, 'cfg', cfg, 'dsr', dsr, ...
                           'insts', insts(s), 'trim_end', trim_end);
end

% find max length and pad any source that is shorter
mlen = max(cellfun('length', d));

for s = 1:S
    if ~isempty(pad_std)
        if pad_std < 0
            pstd = std(d{s}(end-abs(pad_std):end));
        else
            pstd = pad_std;
        end
        d{s} = [d{s} ; pstd*randn(mlen-length(d{s}),1)];
    end
    sdat{s} = st_trans(d{s}, ttype, 'dsr', dsr, 'nfft', nfft, 'win', win, ...
                       'hop', hop, 'bpo', bpo, 'min_freq', minf, 'mag_only', 1);
    sbpr{s} = binary_pianoroll(snmat{s}, size(sdat{s},2), ...
                               'pitches', pitches, 'duration', nmat_dur(mnmat));
end
    